<?php

namespace App\Trip\Orders\BookOrders\Train\PriceDetails;

use App\Models\Setting\Setting;
use App\Models\Trip\TripOrderCosts\TripOrderCost;
use App\Trip\Orders\BookOrders\Train\Order\AbstractOrder\AbstractBuildOrderInfo;
use App\Trip\Orders\BookOrders\Train\PriceDetails\AbstractPriceDetails\AbstractPriceDetails;
use App\Trip\Orders\TripNo;
use App\Trip\Passengers\Passengers;
use App\Trip\Train\Seat\Seats;
use Exception;

class SnapPriceDetails extends AbstractPriceDetails
{
    private array                  $passengers;
    private float                  $service_fee;
    private array                  $price_details;
    private float                  $order_amount;
    private int                    $trip_no;
    private AbstractBuildOrderInfo $orderInfo;

    /**
     * @throws Exception
     */
    public function __construct(AbstractBuildOrderInfo $orderInfo)
    {
        $this->orderInfo   = $orderInfo;
        $this->passengers  = $orderInfo->passengers();
        $this->trip_no     = $orderInfo->getOrderParam()->getTripNo();
        $this->service_fee = $this->getServiceFee();
        $this->buildPriceDetails();
    }

    public function getServiceFee(): float
    {
        /**
         * 线上手续费 目前是  0
         */
        if ($this->orderInfo->getOrderParam()->getOnline() == 1) {
            return 0;
        }
        $setting = new Setting();
        return $setting->TrainOfflineBookServiceFee();
    }

    /**
     * @throws Exception
     */
    private function buildPriceDetails()
    {
        $passengers             = $this->passengers;
        $name                   = TripNo::TRIP_NO_DESC[$this->trip_no];
        $details                = [];
        $total_price            = 0;
        $snap_level_service_fee = $this->orderInfo->getOrderParam()->getSnapParam()->getSnapLevelServiceFee();
        $selected               = $this->orderInfo->getSelectedSeats();
        $snap_selected_seats    = $selected->getSelectedSeats();
        foreach ($snap_selected_seats as $ss) {
            if ($ss['seat_type'] == Seats::SEAT_TYPE_BED) {
                if ($ss['count'] != count($passengers)) {
                    throw new Exception("选座参数错误");
                }
            }
        }

        foreach ($passengers as $key => $passenger) {
            $passenger_type                      = $passenger['passenger_type'];
            $passenger_type_name                 = Passengers::PASSENGER_TYPE_DESC[$passenger_type];
            $passengers[$key]['price_details'][] = [
                "type"  => TripOrderCost::COST_TYPE_TICKET,
                "name"  => Passengers::PASSENGER_TYPE_DESC[$passenger_type],
                "price" => $passenger['seat_price'],
                // TODO  构造订单和乘客 按 照最高价格的车次构造
            ];

            /**
             * 高级加速包 如果开启高速 不收取购票手续费
             */
            if ($snap_level_service_fee > 0) {
                $snap_level_service_fee_key          = "snap_level_service_fee";
                $snap_level_service_fee_type         = TripOrderCost::COST_TYPE_SNAP_HIGH_LEVEL_SERVICE_FEE;
                $snap_level_service_fee_name         = TripOrderCost::COST_TYPE_DESC[TripOrderCost::COST_TYPE_SNAP_HIGH_LEVEL_SERVICE_FEE];
                $passengers[$key]['price_details'][] = [
                    "parent_type" => $snap_level_service_fee_type,
                    "type"        => $snap_level_service_fee_type,
                    "name"        => $snap_level_service_fee_name,
                    "price"       => $snap_level_service_fee,
                ];
                $total_price                         += $snap_level_service_fee;
                if (!isset($details[$snap_level_service_fee_key])) {
                    $details[$snap_level_service_fee_key] = [
                        "type"        => $snap_level_service_fee_type,
                        "parent_type" => $snap_level_service_fee_type,
                        "name"        => $snap_level_service_fee_name,
                        "name_uy"     => trans2uy($snap_level_service_fee_name),
                        "price"       => $snap_level_service_fee,
                        "count"       => 1,
                    ];
                } else {
                    $details[$snap_level_service_fee_key]["count"]++;
                }
                // 高速抢票不收 服务费
                $passengers[$key]['service_fee'] = 0;
            } else {
                $passengers[$key]['service_fee']     = $this->service_fee;
                $passengers[$key]['price_details'][] = [
                    "type"  => TripOrderCost::COST_TYPE_TICKET_SERVICE_FEE,
                    "name"  => "购票手续费",
                    "price" => $this->service_fee,
                ];


                $ticket_service_key  = "ticket_service_fee";
                $ticket_service_type = TripOrderCost::COST_TYPE_TICKET_SERVICE_FEE;
                $ticket_service_name = TripOrderCost::COST_TYPE_DESC[TripOrderCost::COST_TYPE_TICKET_SERVICE_FEE];
                if (!isset($details[$ticket_service_key])) {
                    $details[$ticket_service_key] = [
                        "type"        => $ticket_service_type,
                        "parent_type" => $ticket_service_type,
                        "name"        => $ticket_service_name,
                        "name_uy"     => trans2uy($ticket_service_name),
                        "price"       => $this->service_fee,
                        "count"       => 1,
                    ];
                } else {
                    $details[$ticket_service_key]["count"]++;
                }
                $total_price += $this->service_fee;
            }

            $ticket_price_key  = "snap_ticket_price:".$passenger_type_name;
            $ticket_price_type = TripOrderCost::COST_TYPE_TICKET;
            $ticket_price_name = $passenger_type_name;
            if (!isset($details[$ticket_price_key])) {
                $details[$ticket_price_key] = [
                    "type"        => $ticket_price_type,
                    "parent_type" => $ticket_price_type,
                    "name"        => $ticket_price_name,
                    "name_uy"     => trans2uy($ticket_price_name),
                    "price"       => $passenger['seat_price'],
                    "count"       => 1,
                ];
            } else {
                $details[$ticket_price_key]["count"]++;
            }
            $total_price += $passenger['seat_price'];
        }
        $select_seat_price = $selected->getSelectSeatPrice();
        $select_seat_count = $selected->getSeatsCount();
        $seat_type         = $selected->getSeatType();
        $total_price       += $select_seat_price;
        if ($select_seat_price > 0) {
            $selected_seat_key           = "snap_selected_seat_fee";
            $selected_seat_type          = TripOrderCost::COST_TYPE_SELECT_SEAT;
            $selected_seat_name          = TripOrderCost::COST_TYPE_DESC[TripOrderCost::COST_TYPE_SELECT_SEAT.$seat_type];
            $details[$selected_seat_key] = [
                "type"        => $selected_seat_type,
                "parent_type" => $selected_seat_type,
                "name"        => $selected_seat_name,
                "name_uy"     => trans2uy($selected_seat_name),
                "price"       => $select_seat_count > 0 ? $select_seat_price / $select_seat_count : 0,
                "count"       => $select_seat_count,
            ];
        }
        $this->passengers    = $passengers;
        $this->price_details = [
            'name'        => $name,
            'name_uy'     => trans2uy($name),
            "total_price" => $total_price,
            'details'     => collect($details)->sortBy('type')->values()->toArray(),
        ];
        $this->order_amount  = $total_price;
    }

    public function getPriceDetails(): array
    {
        return $this->price_details;
    }

    public function calcReceivable(): float
    {
        return $this->getOrderAmount();
    }

    public function getOrderAmount(): float
    {
        return $this->order_amount;
    }

    public function calcOriginNeedRefundAmount(): float
    {
        return 0;
    }

    public function getPassengers(): array
    {
        return $this->passengers;
    }
}